package com.fezz.minio;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.fezz.minio.properties.MinioProperties;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FilenameUtils;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

/**
 * MinioTemplate
 *
 * @author muyun
 * @version 1.0.0
 * @since 2020-07-03
 */
@Log4j2
public class MinioTemplate {
    @Getter
    private final String endpoint;
    private final String accessKey;
    private final String secretKey;
    @Setter
    @Getter
    private String bucketName;
    private static volatile MinioClient instance;

    public MinioTemplate(MinioProperties minioProperties) {
        log.info("MinioTemplate init... {} ", minioProperties);
        Assert.notNull(minioProperties, "Minio配置对象为空");
        Assert.notNull(minioProperties.getEndpoint(), "Minio endpoint is null");
        Assert.notNull(minioProperties.getAccessKey(), "accessKey endpoint is null");
        Assert.notNull(minioProperties.getSecretKey(), "Minio secretKey is null");
        Assert.notNull(minioProperties.getBucketName(), "Minio bucketName is null");
        this.endpoint = minioProperties.getEndpoint();
        this.accessKey = minioProperties.getAccessKey();
        this.secretKey = minioProperties.getSecretKey();
        this.bucketName = minioProperties.getBucketName();
    }

    public MinioClient getInstance() throws Exception {
        if (instance == null) {
            synchronized (MinioClient.class) {
                if (instance == null) {
                    instance = new MinioClient(this.endpoint, this.accessKey, this.secretKey);
                }
            }
        }
        return instance;
    }

    /**
     * 上传
     */
    public MinioFile putObject(MultipartFile file) throws Exception {
        MinioFile minioFile = this.generateMinioFile(file, this.bucketName);
        MinioClient minioClient = this.getInstance();
        if (!minioClient.bucketExists(this.bucketName)) {
            minioClient.makeBucket(this.bucketName);
        }
        PutObjectOptions options = new PutObjectOptions(file.getSize(), -1);
        minioClient.putObject(bucketName, minioFile.getUploadedFileName(), file.getInputStream(), options);
        return minioFile;
    }

    /**
     * 上传文件至minio
     *
     * @param byteFiles 文件内容
     * @param fileName  文件名称
     * @return 文件的连接
     */
    public String putObject(byte[] byteFiles, String fileName) throws Exception {
        MinioClient minioClient = this.getInstance();
        if (!minioClient.bucketExists(this.bucketName)) {
            minioClient.makeBucket(this.bucketName);
        }
        InputStream inputStream = new ByteArrayInputStream(byteFiles);
        PutObjectOptions options = new PutObjectOptions(byteFiles.length, -1);
        minioClient.putObject(bucketName, fileName, inputStream, options);
        return this.getEndpoint() + "/" + this.bucketName + "/" + fileName;
    }

    /**
     * 生成MinioFile
     */
    private MinioFile generateMinioFile(MultipartFile file, String bucketName) {
        String originalFilename = FilenameUtils.getName(file.getOriginalFilename());
        String extension = FilenameUtils.getExtension(originalFilename);
        String uploadedFileName = DateUtil.format(DateUtil.date(), "yyyyMMdd") + "_" + IdUtil.simpleUUID() + "." + extension;
        return new MinioFile(originalFilename, uploadedFileName, bucketName);
    }

    /**
     * 获取对象的预签名 URL 以下载其数据 7 天
     */
    public String getObjectUrl(String fileName) throws Exception {
        MinioClient minioClient = this.getInstance();
        return minioClient.presignedGetObject(this.bucketName, fileName);
    }

    /**
     * 删除
     */
    public void removeObject(String fileName) throws Exception {
        this.getInstance().removeObject(this.bucketName, fileName);
    }
}
